﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace WPFTools {
    public class XmlTools {
        public delegate bool NodeConditionDelegate(XmlNode node);
        public static List<XmlNode> SearchAllNodesByName(XmlDocument xmlDoc, string targetNodeName) {
            var result = new List<XmlNode>();
            if (string.IsNullOrEmpty(targetNodeName)) { return result; }
            // 不加这一行就不支持 GB2312 编码
            System.Text.Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            // 
            NodeConditionDelegate nameCondition = (currentNode) => currentNode.Name == targetNodeName;
            SearchIterativelyByCondition(result, xmlDoc, nameCondition);
            return result;
        }
        public static List<XmlNode> SearchAllNodesByName(string xmlDocPath, string targetNodeName) {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlDocPath);
            if(xmlDoc == null) { return new List<XmlNode>(); }
            // 
            var result = SearchAllNodesByName(xmlDoc, targetNodeName);
            return result;
        }
        public static List<XmlNode> SearchAllNodesByAttribute(XmlDocument xmlDoc, string targetNodeName, Dictionary<string, string> dictAttributesAndItsContent) {
            var result = new List<XmlNode>();
            NodeConditionDelegate attributeCondition = (currentNode) => {
                if (currentNode.Name != targetNodeName) {
                    return false;
                }
                var attrs = currentNode.Attributes;
                if(attrs == null) {
                    return false;
                }
                short hitTimes = 0;
                foreach (XmlAttribute attr in attrs) {
                    if (!dictAttributesAndItsContent.Keys.Contains(attr.Name)) {
                        continue;
                    }
                    if (attr.Value == dictAttributesAndItsContent.GetValueOrDefault(attr.Name)) {
                        hitTimes++;
                    }
                }
                return hitTimes == dictAttributesAndItsContent.Count;

            };
            SearchIterativelyByCondition(result, xmlDoc, attributeCondition);
            return result;
        }
        public static void SearchIterativelyByCondition(List<XmlNode> listResult, XmlNode node, NodeConditionDelegate condition) {
            if (listResult == null) {
                listResult = new List<XmlNode>();
            }
            if (node == null || listResult == null) {
                // 抛出异常或处理错误情况
                throw new ArgumentNullException("root or listResult cannot be null.");
            }

            Stack<XmlNode> stack = new Stack<XmlNode>();
            stack.Push(node);

            while (stack.Count > 0) {
                XmlNode currentNode = stack.Pop();

                if (condition(currentNode)) {
                    listResult.Add(currentNode);
                }

                if (currentNode.HasChildNodes) {
                    foreach (XmlNode childNode in currentNode.ChildNodes) {
                        stack.Push(childNode);
                    }
                }
            }
        }
    }
}
